//
//  NSObject+Component.m
//  ComponentLinkDemo
//
//  Created by LevinYan on 2017/3/2.
//  Copyright © 2017年 zhenby. All rights reserved.
//

#import <objc/runtime.h>
#import "CLPComponent.h"
#import "CLPActionPerformer.h"
#import "CLActionEvent_private.h"
#import <UIKit/UIKit.h>
#import "ASDKLink.h"
#import "CLPViewControllerComponent.h"

static const NSString *kComponentIDKey          = @"ComponentIDKey";
static const NSString *kSubcomponentsKey        = @"SubcomponentsKey";
static const NSString *kSupcomponentsKey        = @"SupcomponentsKey";
static const NSString *kActionPerformerKey      = @"ActionPerformerKey";
static const NSString *kCompViewControllerKey   = @"CompViewControllerKey";


@interface NSObject (Component)<CLPComponent>

@property (nonatomic, weak, nullable, readwrite) id<CLPComponent> supercomponent;

@property (nonatomic, weak, nullable) id<CLPActionPerformer> actionPerformer;

@property (nonatomic, strong, readonly, nonnull) NSMutableArray<id<CLPComponent>> *backSubComponents;

@property (nonatomic, strong, nullable) UIViewController *compViewController;


@end

@implementation NSObject (Component)


#pragma mark - runtime instance
- (id<CLPComponent>)supercomponent
{
    return objc_getAssociatedObject(self, &kSupcomponentsKey);
}
- (void)setSupercomponent:(id<CLPComponent>)supercomponent
{
    objc_setAssociatedObject(self, &kSupcomponentsKey, supercomponent, OBJC_ASSOCIATION_ASSIGN);
}
- (NSString*)componentID
{
    return objc_getAssociatedObject(self, &kComponentIDKey);

}
- (void)setComponentID:(NSString *)componentID
{
    objc_setAssociatedObject(self, &kComponentIDKey, componentID, OBJC_ASSOCIATION_COPY);

}
- (NSMutableArray<id<CLPComponent>> *)subComponents
{
    id _subComponents = objc_getAssociatedObject(self, &kSubcomponentsKey);
    if(!_subComponents){
        _subComponents = [NSMutableArray array];
        [self setSubComponents:_subComponents];
    }
    return _subComponents;
}
- (void)setSubComponents:(NSMutableArray<id<CLPComponent>> * _Nonnull)subComponents
{
    objc_setAssociatedObject(self, &kSubcomponentsKey, subComponents, OBJC_ASSOCIATION_RETAIN);
}

- (NSMutableArray<id<CLPComponent>>*) backSubComponents
{
    return (NSMutableArray<id<CLPComponent>>*)self.subComponents;
}

- (id<CLPActionPerformer>)actionPerformer
{
    return objc_getAssociatedObject(self, &kActionPerformerKey);
}
- (void)setActionPerformer:(id<CLPActionPerformer>)actionPerformer
{
    objc_setAssociatedObject(self, &kActionPerformerKey, actionPerformer, OBJC_ASSOCIATION_ASSIGN);
}

- (UIViewController *)compViewController
{
    if ([self conformsToProtocol:@protocol(CLPViewControllerComponent)]) {
        UIViewController *viewController = objc_getAssociatedObject(self, &kCompViewControllerKey);
        if (!viewController) {
            if (!self.layoutSupporter) {
                CLCreateLayoutSupporterWithLayoutElement((id<CLPViewControllerComponent>)self);
            }
            NSAssert([self.layoutSupporter isKindOfClass:[ASDisplayNode class]], @"it must a display node");
            viewController = [[ASViewController alloc] initWithNode:(ASDisplayNode*)self.layoutSupporter];
            ((ASViewController*)viewController).node.backgroundColor = [UIColor whiteColor];
            objc_setAssociatedObject(self, &kCompViewControllerKey, viewController, OBJC_ASSOCIATION_RETAIN);
        }
        
        return viewController;
    }
    
    return nil;
}


#pragma mark -

- (void)addSubcomponent:(nonnull id<CLPComponent>)subcomponent
{
    [self.backSubComponents addObject:subcomponent];
    ((NSObject*)subcomponent).actionPerformer = self.actionPerformer;
    ((NSObject*)subcomponent).supercomponent = self;
    
    if ([subcomponent conformsToProtocol:@protocol(CLPViewComponent)]) {
        id<CLPViewComponent> myComponent = (id<CLPViewComponent>)self;
        [myComponent addSubLayoutElement:(id<CLPViewComponent>)subcomponent];
        
        [(id<CLPViewComponent>)subcomponent loadView];
        ((id<CLPViewComponent>)subcomponent).layoutView = ((id<CLPViewComponent>)subcomponent).view;
    }
    
    NSLog(@"%@",self.subComponents);
}

- (void)removeFromSupercomponent
{
    [((NSObject*)self.supercomponent).backSubComponents removeObject:self];
}
- (void)addSubcomponent:(id<CLPComponent>)subcomponent componentID:(NSString *)componentID
{
    [self.backSubComponents addObject:subcomponent];
    ((NSObject*)subcomponent).supercomponent = self;
}

- (void)exchangeSubcomponentAtIndex:(NSInteger)index1
            withSubcomponentAtIndex:(NSInteger)index2
{
    [self.backSubComponents exchangeObjectAtIndex:index1 withObjectAtIndex:index2];
   
}
- (void)insertSubcomponent:(id<CLPComponent>)subcomponent aboveSubcomponent:(id<CLPComponent>)siblingSubcomponent
{
    NSUInteger index = [self.subComponents indexOfObject:subcomponent];
    [self.backSubComponents insertObject:subcomponent atIndex:index + 1];
}
- (void)insertSubcomponent:(id<CLPComponent>)subcomponent belowComponent:(id<CLPComponent>)siblingSubcomponent
{
    NSUInteger index = [self.subComponents indexOfObject:subcomponent];
    [self.backSubComponents insertObject:subcomponent atIndex:index];
}

- (void)bringSubcomponentToFront:(id<CLPComponent>)subcomponent
{
    [self.backSubComponents removeObject:subcomponent];
    [self.backSubComponents addObject:subcomponent];
}
- (void)sendSubcomponentToBack:(id<CLPComponent>)subcomponent
{
    [self.backSubComponents insertObject:subcomponent atIndex:0];
}
- (nullable id<CLPComponent>)subcomponentWithComponentID:(nonnull NSString *)componentID
{
    id<CLPComponent> subcomponent = nil;
    for(id<CLPComponent> component in self.subComponents){
        if([component.componentID isEqualToString:componentID])
        {
            subcomponent = component;
            break;
        }
    }
    
    return subcomponent;
}

#pragma mark - ActionPerformer

//- (void)performAction:(nonnull CLActionContext *)actionContext
//{
//    [self.actionPerformer performAction:actionContext];
//}
- (void)postActionEvent:(nonnull CLActionEvent *)action
{
    action.fromComponent = self;
    [self.actionPerformer postActionEvent:action];
}

//获取服务事件
- (nullable NSDictionary*)performActionEvent:(nonnull CLActionEvent*)action
{
    if (self.supercomponent && [self.supercomponent respondsToSelector:@selector(performActionEvent:)]) {
        action.fromComponent = self;
        return [self.supercomponent performActionEvent:action];
    }
    return nil;
}

//提供服务事件处理
- (nullable NSDictionary*)actionServiceWithEvent:(nonnull CLActionEvent*)action
{
    if (self.subComponents && self.subComponents.count > 0) {
        NSDictionary* result = nil;
        for (id<CLPComponent> component in self.subComponents) {
            if ([component respondsToSelector:@selector(actionServiceWithEvent:)]) {
                result = [component actionServiceWithEvent:action];
                if (result) {
                    break;
                }
            }
        }
        
        return result;
    }
    
    return nil;
}


@end
